#!/usr/bin/env bash
# bash全局
f_help(){ echo -e "${3}\033[36m[HELP]\033[0m ${1}"; [[ -n "${2}" ]] && exit; }
f_fail(){ echo -e "${3}\033[31m[FAIL]\033[0m ${1}" >&2; [[ -n "${2}" ]] && f_help "${2}"; exit 1; }
f_done(){ echo -e "${3}\033[32m[DONE]\033[0m ${1}"; [[ -n "${2}" ]] && exit; }
f_info(){ echo -e "${3}\033[36m[INFO]\033[0m ${1}"; [[ -n "${2}" ]] && exit; }
f_warn(){ echo -e "${3}\033[34m[WARN]\033[0m ${1}"; [[ -n "${2}" ]] && exit; }
f_wait(){ echo -e "${3}\033[35m[WAIT]\033[0m ${1} ..."; }

# OSTP
if [[ "$(uname -s)" = "Darwin" ]]; then OSTP='mac';
elif [[ -f "/etc/debian_version" ]]; then OSTP='deb';
else f_fail 'unknown os type'; fi;

f_args(){ # rule, help, "$@";  eval set -- "${fx_args_env}";
    fx_args_env=""; local x; local rule=$1; shift; local help=$1; shift;
    while [[ "$#" != "0" ]]; do
        for x in "$@"; do
            [[ "${x}" = "-" ]] || [[ "${x}" = "--" ]] && shift;
            [[ "${x:0:1}" = "-" ]] && break;
            fx_args_env="${fx_args_env} \"${x//\"/\\\"}\"";  shift;
        done;
        while getopts ":${rule}" x; do
            if [[ "${x}" = ":" ]]; then shift; break; fi;
            if [[ "${rule}" = *"${x}:"* ]]; then
                eval "a_${x}=\"${OPTARG//\"/\\\"}\"";
            elif [[ "${rule}" = *"${x}"* ]]; then eval "a_${x}='1'";
            else f_fail "unknown process args: ${OPTARG}"\n"${help}"; fi;
            if [[ "$OPTIND" = "2" ]] || [[ "$OPTIND" = "3" ]]; then
                shift $((OPTIND-1));  OPTIND=1;
            fi;
        done;
    done;
}

f_size(){ # path, [isUnit:1]
    local u='';  [[ "$2" = "1" ]] && u='h';
    if [[ -d "$1" ]]; then
        eval set -- "$(du -${u}d 0 "$1")" || f_fail 'f_size: du';
        echo "$1";
    else
        eval set -- "$(ls -la${u} "$1")" || f_fail 'f_size: ls';
        echo "$5";
    fi;
}

f_mode(){ # path, [mode, dMode, own]
    if [[ -n "$2" ]] && [[ "$2" != "-" ]]; then
        chmod -R "$2" "$1" || f_fail "f_mode: mod $1";
    fi;
    if [[ -n "$3" ]] && [[ "$3" != "-" ]]; then
        chmod "$3" "$1" || f_fail "f_mode: dir $1";
    fi;
    [[ -z "$4" ]] || [[ "$4" = "-" ]] && return;
    chown -R "$4" "$1" || f_fail "f_mode: own $1";
}

f_copy(){ # src tar, [mode, dMode, own]
    mkdir -p "$(dirname $2)" || f_fail "f_copy: mkdir $2/..";
    cp -rfT "$1" "$2" || f_fail "f_copy: $2";
    f_mode "$2" "$3" "$4" "$5";
}

f_bkup(){ # path, [isDel:1, mode, dMode, own]
    local s=$1;  local b="${s}.backup";
    if [[ ! -f "${s}" ]] && [[ ! -d "${s}" ]]; then
        [[ ! -f "${b}" ]] && [[ ! -d "${b}" ]] && return;
        f_mode "${b}" "$3" "$4" "$5";
        [[ -L "${s}" ]] && return;
        [[ "$2" != "1" ]] && f_copy "${b}" "${s}" "$3" "$4" "$5";
        return;
    fi;
    [[ -L "$1" ]] && s=$(realpath "$1");
    if [[ -f "${b}" ]] || [[ -d "${b}" ]]; then
        f_mode "${b}" "$3" "$4" "$5";
        if [[ "${2}" != "1" ]]; then f_mode "${s}" "$3" "$4" "$5";
        else rm -rf "${s}" || f_fail "f_bkup: del ${s}"; fi;
    elif [[ "${2}" != "1" ]]; then
        f_mode "${s}" "$3" "$4" "$5";
        f_copy "${s}" "${b}" "$3" "$4" "$5";
    else
        mv "${s}" "${b}" || f_fail "f_bkup: ${s}";
        f_mode "${b}" "$3" "$4" "$5";
    fi;
}

f_link(){ # has, new, [own]
    if [[ ! -L "$2" ]] || [[ "$(readlink \"$2\")" != "$1" ]]; then
        rm -rf "$2" || f_fail "f_link: delete $2";
        ln -s "$1" "$2" || f_fail "f_link: create $2";
    fi;
    [[ -z "$3" ]] || [[ "$3" = "-" ]] && return;
    chown "$3" "$2" || f_fail "f_link: own $2";
}

echo > /dev/null;
